package com.niodata.dp.init;

import com.niodata.dp.core.ConfigurationKeys;
import com.niodata.dp.core.DpConfiguration;
import com.niodata.dp.core.hdfs.HdfsFileSystem;
import com.niodata.dp.core.service.SystemServiceManager;
import com.niodata.dp.core.service.SystemServices;
import com.niodata.dp.core.usermgr.enums.SystemRole;
import com.niodata.dp.core.usermgr.model.UserInfo;
import com.niodata.dp.core.usermgr.op.GroupInfoService;
import com.niodata.dp.core.usermgr.op.UserService;
import com.niodata.dp.core.usermgr.op.kl.KdcLdapOperation;
import com.niodata.dp.log.LogUtil;
import com.niodata.dp.mybatis.MyBatisConfiguration;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.log4j.Logger;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;


@ComponentScan(basePackages = {"com.niodata.dp"},
      excludeFilters =
      @ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.niodata.dp.web.*"))
@Import(MyBatisConfiguration.class)
@MapperScan("com.niodata.dp")
@PropertySources(value =
      {@PropertySource("classpath:application.properties"),
            @PropertySource("classpath:hdfs.properties"),
            @PropertySource("classpath:datasource.properties"),
            @PropertySource("classpath:hive.properties"),
            @PropertySource("classpath:monitor.properties"),
            @PropertySource("classpath:quartz.properties"),
            @PropertySource("classpath:redis.properties"),
            @PropertySource("classpath:workflow.properties"),
            @PropertySource("classpath:plugin.properties")})
@Service
public class SystemInitializer {

  private static final Logger logger = Logger.getLogger(SystemInitializer.class);

  @Autowired
  @Qualifier("DpUserMgrUser")
  private UserService userService;

  @Autowired
  @Qualifier("DpUserMgrGroup")
  private GroupInfoService groupInfoService;

  @Autowired
  private SystemServiceManager systemServiceManager;

  public static void main(String[] args) throws Exception {
    ApplicationContext context = new AnnotationConfigApplicationContext(SystemInitializer.class);
    SystemInitializer initializer = context.getBean(SystemInitializer.class);
    initializer.initSystemService();
    initializer.initSuperAdmin();
    if (DpConfiguration.isHadoopEnabled()) {
      initializer.initHdfs();
    }
    System.exit(0);
  }

  /**
   * init hdfs dir.
   */
  public void initHdfs() {
    //create 'All' group
    String superGroup = DpConfiguration.getString("hdfs.super.group");
    String superUser = DpConfiguration.getString("hdfs.super.user");
    // /dp hadoop supergroup
    HdfsFileSystem.getInstance().mkdir(DpConfiguration.getDpHdfsRootDir(),
          superUser, superGroup,
          new FsPermission(FsAction.ALL, FsAction.READ_EXECUTE, FsAction.EXECUTE));
    // /dp/users hadoop supergroup
    HdfsFileSystem.getInstance().mkdir(DpConfiguration.getDpHdfsUsersRootDir(),
          superUser, superGroup,
          new FsPermission(FsAction.ALL, FsAction.READ_EXECUTE, FsAction.READ_EXECUTE));
    // /dp/groups hadoop supergroup
    HdfsFileSystem.getInstance().mkdir(DpConfiguration.getDpHdfsGroupsRootDir(),
          superUser, superGroup,
          new FsPermission(FsAction.ALL, FsAction.READ_EXECUTE, FsAction.EXECUTE));
    // /dp/public hadoop supergroup
    //HdfsFileSystem.getInstance().mkdir(conf.getDpHdfsPublicDir(), superUser, superGroup,
    //    new FsPermission(FsAction.ALL, FsAction.READ_EXECUTE, FsAction.READ_WRITE));
    // /dp/data hadoop supergroup
    HdfsFileSystem.getInstance().mkdir(DpConfiguration.getDpHdfsDataRootDir(),
          superUser, superGroup,
          new FsPermission(FsAction.ALL, FsAction.READ_WRITE, FsAction.EXECUTE));
  }

  private void initSuperAdmin() {
    String superadminHdfsUser = "superadmin";
    if (DpConfiguration.isKerberosEnabled()) {
      try {
        KdcLdapOperation.getInstance().removeUser(superadminHdfsUser,
              Arrays.asList(new String[]{}));
      } catch (Exception e) {
        LogUtil.logStackTrace(logger, e);
      }
    }
    UserInfo superAdmin = new UserInfo();
    superAdmin.setUserName("superadmin");
    superAdmin.setLoginName("superadmin");
    String password = DpConfiguration.getString(ConfigurationKeys.SYSTEM_SUPERADMIN_INIT_PWD,
          "4ch~Cs4R");
    BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    String encoded = encoder.encode(password);
    superAdmin
          .setPassword(encoded);
    superAdmin.setCreateTime(new Timestamp(new Date().getTime()));
    superAdmin.setHdfsHome(DpConfiguration.getDpHdfsUsersRootDir()
          + "/superadmin");
    superAdmin.setDetail("system super admin");
    superAdmin.setRole(SystemRole.SUPERADMIN);
    superAdmin.setEmail("superadmin@ndp.com");
    superAdmin.setHdfsUser(superadminHdfsUser);
    this.userService.createUser(superAdmin);
  }


  public void initSystemService() {
    systemServiceManager.addSystemService(SystemServices.getServcieList());
  }

}
